package com.news.util;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;

/**
 * HTTP工具类
 */
public class HttpUtil {
    
    private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);
    
    private static final int TIMEOUT = 8000; // 减少到8秒超时
    private static final int RETRY_COUNT = 2; // 重试次数
    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36";
    
    private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom()
            .setConnectTimeout(TIMEOUT)
            .setSocketTimeout(TIMEOUT)
            .setConnectionRequestTimeout(TIMEOUT)
            .build();
    
    /**
     * 发送GET请求（带重试机制）
     * @param url 请求URL
     * @return 响应内容
     * @throws IOException 请求异常
     */
    public static String get(String url) throws IOException {
        return get(url, RETRY_COUNT);
    }
    
    /**
     * 发送GET请求
     * @param url 请求URL
     * @param retryCount 重试次数
     * @return 响应内容
     * @throws IOException 请求异常
     */
    private static String get(String url, int retryCount) throws IOException {
        logger.debug("发送GET请求: {} (剩余重试次数: {})", url, retryCount);
        
        Exception lastException = null;
        
        for (int i = 0; i <= retryCount; i++) {
            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
                HttpGet httpGet = new HttpGet(url);
                httpGet.setConfig(REQUEST_CONFIG);
                httpGet.setHeader("User-Agent", USER_AGENT);
                httpGet.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
                httpGet.setHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
                httpGet.setHeader("Accept-Encoding", "gzip, deflate");
                httpGet.setHeader("Connection", "keep-alive");
                
                try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                    int statusCode = response.getStatusLine().getStatusCode();
                    if (statusCode == 200) {
                        String content = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                        logger.debug("请求成功，响应长度: {}", content.length());
                        return content;
                    } else {
                        String errorMsg = "HTTP请求失败，状态码: " + statusCode;
                        logger.warn(errorMsg);
                        if (i == retryCount) {
                            throw new IOException(errorMsg);
                        }
                    }
                }
            } catch (UnknownHostException e) {
                lastException = e;
                logger.warn("DNS解析失败 (第{}次尝试): {} - {}", i + 1, url, e.getMessage());
                if (i == retryCount) {
                    throw new IOException("DNS解析失败，无法访问: " + url, e);
                }
                // DNS错误通常不需要重试，直接失败
                break;
            } catch (SocketTimeoutException e) {
                lastException = e;
                logger.warn("请求超时 (第{}次尝试): {} - {}", i + 1, url, e.getMessage());
                if (i == retryCount) {
                    throw new IOException("请求超时: " + url, e);
                }
                // 超时错误可以重试
                try {
                    Thread.sleep(1000 * (i + 1)); // 递增延迟
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new IOException("请求被中断", ie);
                }
            } catch (IOException e) {
                lastException = e;
                logger.warn("网络请求失败 (第{}次尝试): {} - {}", i + 1, url, e.getMessage());
                if (i == retryCount) {
                    throw e;
                }
                // 其他IO错误可以重试
                try {
                    Thread.sleep(500 * (i + 1)); // 递增延迟
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new IOException("请求被中断", ie);
                }
            }
        }
        
        // 如果所有重试都失败了
        if (lastException != null) {
            throw new IOException("请求失败，已重试" + retryCount + "次", lastException);
        }
        
        throw new IOException("未知错误");
    }
    
    /**
     * 发送GET请求并返回JSON
     * @param url 请求URL
     * @return JSON字符串
     * @throws IOException 请求异常
     */
    public static String getJson(String url) throws IOException {
        logger.debug("发送JSON GET请求: {}", url);
        
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setConfig(REQUEST_CONFIG);
            httpGet.setHeader("User-Agent", USER_AGENT);
            httpGet.setHeader("Accept", "application/json, text/javascript, */*; q=0.01");
            httpGet.setHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
            httpGet.setHeader("X-Requested-With", "XMLHttpRequest");
            
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode == 200) {
                    String content = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                    logger.debug("JSON请求成功，响应长度: {}", content.length());
                    return content;
                } else {
                    logger.warn("JSON请求失败，状态码: {}", statusCode);
                    throw new IOException("HTTP请求失败，状态码: " + statusCode);
                }
            }
        } catch (UnknownHostException e) {
            logger.warn("DNS解析失败: {} - {}", url, e.getMessage());
            throw new IOException("DNS解析失败，无法访问: " + url, e);
        } catch (SocketTimeoutException e) {
            logger.warn("JSON请求超时: {} - {}", url, e.getMessage());
            throw new IOException("请求超时: " + url, e);
        }
    }
    
    /**
     * 检查URL是否可访问（简化版，不重试）
     * @param url 要检查的URL
     * @return 是否可访问
     */
    public static boolean isAccessible(String url) {
        try {
            logger.debug("检查URL可访问性: {}", url);
            
            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
                HttpGet httpGet = new HttpGet(url);
                // 使用更短的超时时间进行可访问性检查
                RequestConfig quickConfig = RequestConfig.custom()
                        .setConnectTimeout(3000)
                        .setSocketTimeout(3000)
                        .setConnectionRequestTimeout(3000)
                        .build();
                httpGet.setConfig(quickConfig);
                httpGet.setHeader("User-Agent", USER_AGENT);
                
                try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                    int statusCode = response.getStatusLine().getStatusCode();
                    boolean accessible = statusCode >= 200 && statusCode < 400;
                    logger.debug("URL {} 可访问性检查结果: {} (状态码: {})", url, accessible, statusCode);
                    return accessible;
                }
            }
        } catch (UnknownHostException e) {
            logger.debug("DNS解析失败，URL不可访问: {} - {}", url, e.getMessage());
            return false;
        } catch (SocketTimeoutException e) {
            logger.debug("连接超时，URL不可访问: {} - {}", url, e.getMessage());
            return false;
        } catch (IOException e) {
            logger.debug("网络错误，URL不可访问: {} - {}", url, e.getMessage());
            return false;
        } catch (Exception e) {
            logger.debug("未知错误，URL不可访问: {} - {}", url, e.getMessage());
            return false;
        }
    }
    
    /**
     * 获取错误信息的简化描述
     * @param e 异常
     * @return 简化的错误描述
     */
    public static String getSimpleErrorMessage(Exception e) {
        if (e instanceof UnknownHostException) {
            return "DNS解析失败，无法连接到服务器";
        } else if (e instanceof SocketTimeoutException) {
            return "连接超时，请检查网络";
        } else if (e instanceof IOException) {
            return "网络连接错误: " + e.getMessage();
        } else {
            return "未知错误: " + e.getMessage();
        }
    }
} 